package com.koushikdutta.async.slice;

import com.koushikdutta.async.ResourceTable;
import com.koushikdutta.async.base.BaseAbilitySlice;
import com.koushikdutta.async.utils.FileUtils;
import com.koushikdutta.async.utils.Toast;
import com.koushikdutta.async.ByteBufferList;
import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.http.AsyncHttpClient;
import com.koushikdutta.async.http.AsyncHttpGet;
import com.koushikdutta.async.http.AsyncHttpPost;
import com.koushikdutta.async.http.AsyncHttpRequest;
import com.koushikdutta.async.http.AsyncHttpResponse;
import com.koushikdutta.async.http.BasicNameValuePair;
import com.koushikdutta.async.http.NameValuePair;
import com.koushikdutta.async.http.WebSocket;
import com.koushikdutta.async.http.body.MultipartFormDataBody;
import com.koushikdutta.async.http.body.UrlEncodedFormBody;
import com.koushikdutta.async.http.cache.ResponseCacheMiddleware;
import com.koushikdutta.async.util.LogUtil;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.Text;
import ohos.agp.components.element.PixelMapElement;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import ohos.utils.net.Uri;
import ohos.utils.zson.ZSONArray;
import ohos.utils.zson.ZSONObject;

import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;

/**
 * Here is a note copy.
 */
public class MainAbilitySlice extends BaseAbilitySlice implements Component.ClickedListener {
    private static final String LOGTAG = "AsyncSample-->";
    static ResponseCacheMiddleware cacher;
    private Button downloadPicture;
    private Button downloadString;
    private Image rommanager;
    private Image tether;
    private Image desksms;
    private Image chart;
    private Text textString;

    @Override
    protected int getLayout() {
        return ResourceTable.Layout_ability_main;
    }

    @Override
    protected void initView() {
        downloadPicture = (Button) findComponentById(ResourceTable.Id_downloadPicture);
        rommanager = (Image) findComponentById(ResourceTable.Id_rommanager);
        tether = (Image) findComponentById(ResourceTable.Id_tether);
        desksms = (Image) findComponentById(ResourceTable.Id_desksms);
        chart = (Image) findComponentById(ResourceTable.Id_chart);
        textString = (Text) findComponentById(ResourceTable.Id_text_string);
        downloadString = (Button) findComponentById(ResourceTable.Id_downloadString);
        downloadPicture.setClickedListener(this);
        downloadString.setClickedListener(this);

        if (cacher == null) {
            try {
                cacher = ResponseCacheMiddleware.addCache(AsyncHttpClient.getDefaultInstance(), FileUtils.createCach(getContext()), 1024 * 1024 * 10);
                cacher.setCaching(false);
            } catch (IOException e) {
                Toast.show(getContext(), "unable to create cache");
            }
        }

        showCacheToast();
    }

    @Override
    protected void initData() {

    }

    //https://httpbin.org/get
    @Override
    public void onClick(Component component) {
        switch (component.getId()) {
            case ResourceTable.Id_downloadPicture:
                try {
                    refresh();
                } catch (IOException e) {
                    LogUtil.info("IOException",e.getMessage());
                }
                break;
            case ResourceTable.Id_downloadString:
                getHttpString();
//                getJsonArray();
                break;
        }
    }


    private void getHttpString() {
        Uri parse = Uri.parse("https://httpbin.org/get");
        AsyncHttpRequest get = new AsyncHttpRequest(parse, "GET");
        AsyncHttpClient.getDefaultInstance().executeString(get, new AsyncHttpClient.StringCallback() {
            @Override
            public void onCompleted(Exception e, AsyncHttpResponse source, String result) {
                LogUtil.info(LOGTAG, result);

                new EventHandler(EventRunner.getMainEventRunner()).postTask(new Runnable() {
                    @Override
                    public void run() {
                        textString.setText(result);
                    }
                });
            }
        });
    }

    /**
     * Download JSON from a url
     */
    private void getJsonUrl() {
        Uri parse = Uri.parse("http://api.androidhive.info/volley/person_object.json");
        AsyncHttpRequest get = new AsyncHttpRequest(parse, "GET");
        AsyncHttpClient.getDefaultInstance().executeJSONObject(get, new AsyncHttpClient.JSONObjectCallback() {
            @Override
            public void onCompleted(Exception e, AsyncHttpResponse source, ZSONObject result) {
                if(resultJudgment(e)){
                    return;
                }
                LogUtil.info(LOGTAG, result.toString());
            }
        });
    }

    /**
     * Or for JSONArrays...
     */
    private void getJsonArray() {
        Uri parse = Uri.parse("https://www.wanandroid.com//hotkey/json");
        AsyncHttpRequest get = new AsyncHttpRequest(parse, "GET");
        AsyncHttpClient.getDefaultInstance().executeJSONArray(get, new AsyncHttpClient.JSONArrayCallback() {
            @Override
            public void onCompleted(Exception e, AsyncHttpResponse source, ZSONArray result) {
                if(resultJudgment(e)){
                    return;
                }
                LogUtil.info(LOGTAG, result.toString());
            }
        });

    }

    /**
     * Caching is supported too
     */

    private void setCaching() {
        try {
            ResponseCacheMiddleware.addCache(AsyncHttpClient.getDefaultInstance(), FileUtils.createCach(getContext()), 1024 * 1024 * 10);
        } catch (IOException e) {
            LogUtil.info("IOException",e.getMessage());
        }
    }

    /**
     * Need to do multipart/form-data uploads? That works too.
     */
    void showCacheToast() {
        boolean caching = cacher.getCaching();
        Toast.show(getContext(), "Caching: " + caching);
    }

    /**
     * Need to do multipart/form-data uploads? That works too
     *
     * @throws IOException
     */
    private void multipartForm() {
        AsyncHttpPost post = new AsyncHttpPost("http://myservercom/postform.html");
        MultipartFormDataBody body = new MultipartFormDataBody();
        body.addFilePart("my-file", new File("/path/to/file.txt"));
        body.addStringPart("foo", "bar");
        post.setBody(body);
        AsyncHttpClient.getDefaultInstance().executeString(post, new AsyncHttpClient.StringCallback() {
            @Override
            public void onCompleted(Exception ex, AsyncHttpResponse source, String result) {
                if (ex != null) {
                    LogUtil.info("IOException",ex.getMessage());
                    return;
                }
                LogUtil.info("Server says: ", result);
            }
        });
    }

    /**
     * Can also create web sockets
     *
     * @throws IOException
     */
    private void sockets() {
        AsyncHttpClient.getDefaultInstance().websocket("get", "my-protocol", new AsyncHttpClient.WebSocketConnectCallback() {
            @Override
            public void onCompleted(Exception ex, WebSocket webSocket) {
                if (ex != null) {
                    LogUtil.info("IOException",ex.getMessage());
                    return;
                }
                webSocket.send("a string");
                webSocket.send(new byte[10]);
                webSocket.setStringCallback(new WebSocket.StringCallback() {

                    /**
                     * Here is a note copy.
                     *
                     * @param s insert this using
                     */
                    public void onStringAvailable(String s) {
                    }
                });
                webSocket.setDataCallback(new DataCallback() {

                    /**
                     * Here is a note copy.
                     *
                     * @param emitter Here is a note copy.
                     * @param byteBufferList Here is a note copy.
                     */
                    public void onDataAvailable(DataEmitter emitter, ByteBufferList byteBufferList) {
                        LogUtil.info("I got some bytes!", "");
                        // note that this data has been read
                        byteBufferList.recycle();
                    }
                });
            }
        });
    }


    private void refresh() throws IOException {
        rommanager.setImageElement(null);
        tether.setImageElement(null);
        desksms.setImageElement(null);
        chart.setImageElement(null);


        getFile(rommanager, "https://github.com/dfaker/df/raw/master/finalmerged.jpg", FileUtils.createFile(getContext(), randomFile()));
        getFile(tether, "https://github.com/dfaker/df/raw/master/finalmerged.jpg", FileUtils.createFile(getContext(), randomFile()));
        getFile(desksms, "https://github.com/dfaker/df/raw/master/finalmerged.jpg", FileUtils.createFile(getContext(), randomFile()));
//        getChartFile();

        LogUtil.info(LOGTAG, "cache hit: " + cacher.getCacheHitCount());
        LogUtil.info(LOGTAG, "cache store: " + cacher.getCacheStoreCount());
        LogUtil.info(LOGTAG, "conditional cache hit: " + cacher.getConditionalCacheHitCount());
        LogUtil.info(LOGTAG, "network: " + cacher.getNetworkCount());
    }


    private void getFile(final Image iv, String url, final String filename) {

        AsyncHttpClient.getDefaultInstance().executeFile(new AsyncHttpGet(url), filename, new AsyncHttpClient.FileCallback() {
            @Override
            public void onCompleted(Exception e, AsyncHttpResponse response, File result) {
                if (e != null) {
                    LogUtil.info("IOException",e.getMessage());
                    return;
                }
                createBitMap(iv, filename, result);
            }
        });
    }

    private void assignImageView(final Image iv, final PixelMapElement bd) {

        iv.getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
            @Override
            public void run() {
                iv.setImageElement(bd);
            }
        });
    }


    private void getChartFile() throws IOException {
        final Image iv = chart;
        final String filename = FileUtils.createFile(getContext(), randomFile());
        ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
        pairs.add(new BasicNameValuePair("cht", "lc"));
        pairs.add(new BasicNameValuePair("chtt", "This is a google chart"));
        pairs.add(new BasicNameValuePair("chs", "512x512"));
        pairs.add(new BasicNameValuePair("chxt", "x"));
        pairs.add(new BasicNameValuePair("chd", "t:40,20,50,20,100"));
        UrlEncodedFormBody writer = new UrlEncodedFormBody(pairs);
        try {
            // http://chart.googleapis.com/chart
            AsyncHttpPost post = new AsyncHttpPost("http://chart.googleapis.com/chart");
            post.setBody(writer);
            AsyncHttpClient.getDefaultInstance().executeFile(post, filename, new AsyncHttpClient.FileCallback() {
                @Override
                public void onCompleted(Exception e, AsyncHttpResponse response, File result) {
                    if (e != null) {
                        LogUtil.info("IOException",e.getMessage());
                        return;
                      }
                    createBitMap(iv, filename, result);
                }
            });
        } catch (Exception ex) {
            LogUtil.info("IOException",ex.getMessage());
        }
    }

    private String randomFile() {
        SecureRandom random = new SecureRandom();

        int round = Math.round(random.nextInt(1001));
        return round + ".png";
    }

    private void createBitMap(Image iv, String fileName, File result) {
        ImageSource imageSource = ImageSource.create(fileName, null);
        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        decodingOpts.desiredSize = new Size(300, 300);
        decodingOpts.desiredRegion = new Rect(0, 0, 300, 300);
        decodingOpts.rotateDegrees = 90;
        PixelMap bitmap = imageSource.createPixelmap(decodingOpts);
        if(result.delete()){
            LogUtil.error("result","ok");
        }
        if (bitmap == null){
            return;
        }
        PixelMapElement bd = new PixelMapElement(bitmap);
        assignImageView(iv, bd);
    }
    /**
     * 请求结果信息判断
     */
    private boolean resultJudgment(Exception e) {
        if (e != null) {
            LogUtil.error(LOGTAG, e.getMessage());
            return true;
        }
        return false;
    }
}
